<?php

namespace App\Http\Controllers {

    use App\Common\AutoinjectTrait;
    use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
    use Illuminate\Foundation\Bus\DispatchesJobs;
    use Illuminate\Foundation\Validation\ValidatesRequests;
    use Illuminate\Routing\Controller as BaseController;
    use Illuminate\Http\Response;
    use OpenApi\Attributes as OA;


    #[OA\SecurityScheme(securityScheme: 'sanctum', type: 'http', scheme: 'bearer', description: 'Sanctum API授权')]
    #[OA\OpenApi(
        openapi: OA\OpenApi::DEFAULT_VERSION,
        info: new OA\Info(
            title: 'ruoyi-laraval-admin后台管理系统',
            version: 1.0,
            description: '基于ruoyi.vip前后端分离',
            contact: new OA\Contact(name: 'zwping', email: 'zwping.com@gmail.com'),
            license: new OA\License(name: 'MIT'),
        ),
        servers: [
            new OA\Server(url:'http://ruoyiapi.zwp.cc', description:'zwp本地环境'),
            new OA\Server(url:'https://ruoyiapi.zwping.com', description:'正式环境s'),
        ],
        security: [['sanctum' => []]],  # apifox不适用该参数
        tags: [
            new OA\Tag(name: '后端', description: '后端接口'),
            new OA\Tag(name: '前端', description: '前端接口'),
        ],
    )]
    class Controller extends BaseController {
        use AuthorizesRequests, DispatchesJobs, ValidatesRequests, AutoinjectTrait;


        public function __construct() {
            $this->inject();
        }


        // ====================

        /**
         * 标准bean
         * @param mixed  $data 根data, 一定是json object
         * @param string $msg
         * @param int    $code
         * @param string $response_type
         * @return Response
         */
        protected function bean(?array $data = null, ?string $msg = '请求成功~', int $code = 200): Response
        {
    //        dd($data, gettype($data), gettype([1]), is_array($data), count($data));
            // if (is_scalar($data)) {
            //     if (strlen($data) == 0) {
            //         $data = (object)[];                     // { "data": {} }
            //     } else {
            //         $data = (object) ['text' => $data];     // { "data": { "text": scalar } }
            //     }
            // } elseif ($data instanceof Collection || (is_array($data) && $this->array_is_list($data))) {
            //     $data = (object)['list' => $data];          // { "data": { "list": [] } }
            // } else {
            //     $data = (object)$data;                      // { "data": { json object } }
            // }
            // $root_data = [
            //     'code'  =>  $code,
            //     'msg'   =>  $msg,
            //     'data'  =>  $data,                          // 保证根data是object
            // ];
            return show_response($data, $msg, $code);
        }

        protected function beanErr($msg, $code=400) {
            return $this->bean(null, is_string($msg) ? $msg : json_encode($msg), $code);
        }

        /**
         * 分页
         */
        protected function page_size(Int $default=20): Int {
            $page_size = (int) request('page_size', $default);
            return ($page_size > 100) ? 100 : ($page_size < 0 ? 1 : $page_size);
        }
        protected function page(): Int { return intval(request('page', 1)); }
        protected function pag(): array { return ['page'=>$this->page(), 'per_page'=>$this->page_size()]; }

        /**
         * 统一校验规则
         * @param array $rule 当前控制器所有参数的校验规则
         * @param array $keys 路由需要的校验参数
         * @param array $append 追加/覆盖的校验规则
         */
        protected function rules(array $rule, $keys, /* $excepts=null, */ array $append=null): array {
            $result = [];
            if (is_string($keys)) { $result[$keys] = $rule[$keys]; }
            else { foreach($keys as $k) { $result[$k] = $rule[$k]; } }
            return $append ? array_merge($result ?: $rule, $append) : ($result ?: $rule);
        }

        /**
         * 判断array是否为一个正常的数组, 下标从0开始递增(未设置下标)
         * @param array $array
         * @return bool
         */
        function array_is_list(array $array): bool {
            if (empty($array)) { return true; }
            $current_key = 0;
            foreach ($array as $key => $noop) {
                if ($key !== $current_key) { return false; }
                ++$current_key;
            }
            return true;
        }

    }
}


namespace App\Http\Controllers\CommonBean {

    use OpenApi\Attributes as OA;

    #[OA\Schema(title: '参数/后台异常', required: ['code', 'msg'],)]
    class Service500ErrBean {
        #[OA\Property(type: 'int', default: 500, example: '40x/50x', description: '40x为用户(参数)错误, 50x为后台逻辑错误')] public $code;
        #[OA\Property(type: 'string', example: '后台异常 !', description: 'code非200取msg用于toast')] public $msg;
        #[OA\Property(type: 'string', description: '异常的堆栈信息, debug模式才会输出')] public $errorstack;
    }

    #[OA\Schema(title: 'Paging', description: '分页对象', required: ['page', 'page_size', 'total'],)]
    class Paging {
        #[OA\Property(type: 'int', default: 1, example: 1, description: '当前页')] public $page;
        #[OA\Property(type: 'int', default: 20, example: 20, description: '每页数量')] public $page_size;
        #[OA\Property(type: 'int', default: 0, example: 100, description: '结果总数')] public $total;
    }

}
